home *** CD-ROM | disk | FTP | other *** search
/ World of Education / World of Education.iso / world_x / xcoral16.zip / BM_SEARC.C < prev    next >
C/C++ Source or Header  |  1993-01-15  |  14KB  |  616 lines

  1. /*
  2. ** Copyright 1989, 1992 by Lionel Fournigault
  3. **
  4. ** Permission to use, copy, and distribute for non-commercial purposes,
  5. ** is hereby granted without fee, providing that the above copyright
  6. ** notice appear in all copies and that both the copyright notice and this
  7. ** permission notice appear in supporting documentation.
  8. ** The software may be modified for your own purposes, but modified versions
  9. ** may not be distributed.
  10. ** This software is provided "as is" without any expressed or implied warranty.
  11. **
  12. **
  13. */
  14.  
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <malloc.h>
  18. #include <X11/Xlib.h>
  19.  
  20. #include "text.h"
  21. #include "flist.h"
  22.  
  23. static char *str_save = 0;
  24. static char *str_old = 0;
  25. static char *str_new = 0;
  26. static int abort_debug = False;
  27.  
  28. #define FORWARD    1
  29. #define BACKWARD    -1
  30. #define GLOBAL    1
  31. #define QUERY    2
  32. #define S_MENU    0
  33. #define S_KBD    1
  34.  
  35. extern Display *dpy;
  36. static void HandleForward (), HandleBackward (), HandleGlobal ();
  37. static int SetReplaceString (), BmSearch ();
  38. static char *SetString();
  39.  
  40.  
  41. /*
  42. **    Function name : ForwardSearch
  43. **
  44. **    Description : Prepare la recherche vers l'avant.
  45. **
  46. **    Input : Le text courant.
  47. **    Ouput :
  48. */
  49. void ForwardSearch ( text )
  50.     Text *text;
  51. {
  52.     register char *str;
  53.  
  54.         if ( (str = (char *) SetString ( text, "Forward search : ", S_KBD )) == 0 )  {
  55.         DisplayMessage ( text -> mwin, "Abort" );
  56.         return;
  57.     }
  58.     else
  59.         DisplayMessage ( text -> mwin, "Search..." );
  60.     
  61.         HandleForward ( str, text );
  62. }
  63.  
  64.  
  65. /*
  66. **    Function name : HandleForward
  67. **
  68. **    Description : Recherche vers l'avant la chaine 'str'
  69. **
  70. **    Input : La chaine recherchee, le text courant.
  71. **    Ouput :
  72. */
  73. static void HandleForward ( str, text )    
  74. register char *str;
  75. Text *text;
  76. {    
  77.     register int newpos;
  78.     register char *start,  *end;
  79.  
  80.     start = (char *) RightBuf ( text -> buf ); 
  81.     end = (char *) BottomBuf ( text -> buf );
  82.  
  83.     if ( (newpos=BmSearch( start, str,  end -start, FORWARD )) != -1 ) {
  84.         if ( newpos == 0 ) {     /* On est pile dessus */
  85.             (void) MoveHole ( text -> buf, 1 );    /* Voyons plus loin */
  86.             start ++;
  87.             if ( (newpos=BmSearch( start, str,  end - start, FORWARD )) == -1 ) {
  88.                 DisplayMessage ( text -> mwin, "Search failed" );
  89.                 klaxon ();
  90.                 (void) MoveHole ( text -> buf, -1 );
  91.                 return;
  92.             }
  93.         }
  94.         GotoPos ( text, start, newpos, FORWARD );
  95.         return;
  96.     }
  97.     DisplayMessage ( text -> mwin, "Search failed" );
  98.     klaxon ();
  99. }
  100.  
  101.  
  102. /*
  103. **    Function name : BackwardSearch
  104. **
  105. **    Description : Prepare la recherche vers l'arriere.
  106. **
  107. **    Input : Le text.
  108. **    Ouput :
  109. */
  110. void BackwardSearch ( text )
  111.     Text *text;
  112. {
  113.     register char *str;
  114.  
  115.     if ( (str = (char *) SetString ( text, "Backward search : ", S_KBD )) == 0 ) {
  116.         DisplayMessage ( text -> mwin, "Abort" );
  117.         return;
  118.     }
  119.     else
  120.         DisplayMessage ( text -> mwin, "Search..." );    
  121.  
  122.     HandleBackward ( str, text );
  123. }
  124.  
  125.  
  126. /*
  127. **    Function name : HandleBackward
  128. **
  129. **    Description : Recherche vers l'arriere la chaine 'str'
  130. **
  131. **    Input :  La chaine recherchee, le text courant.
  132. **    Ouput :
  133. */
  134. static void HandleBackward ( str, text )
  135. register char *str;
  136. Text *text;
  137. {
  138.     register int newpos, oldpos;
  139.     register char *start,  *end;
  140.     int len;
  141.  
  142.     oldpos = GetNcFromRight ( text -> buf );
  143.     start = (char *) GetCurrentLine ( text -> buf, &len );
  144.     end = (char *) TopBuf ( text -> buf );
  145.  
  146.     start += ( len -1);    /* On part de la fin de la ligne */
  147.     if ( (newpos=BmSearch( start, str, len -1, BACKWARD )) != -1 ) {
  148.         if ( (newpos - oldpos) > 0 ) { /* On est a l'interieur */
  149.             (void) MoveHole ( text -> buf, -(newpos - oldpos) );
  150.             return;
  151.         }
  152.     }
  153.     start = (char *) LeftBuf ( text -> buf ); /* Allons voir plus loin */
  154.  
  155.     if ( (newpos=BmSearch ( start, str,  start - end, BACKWARD )) == -1 ) {
  156.         DisplayMessage ( text -> mwin, "Search failed" );
  157.         klaxon ();
  158.         return;
  159.     }    
  160.     GotoPos ( text, start, newpos, BACKWARD );
  161.     return;
  162. }
  163.  
  164.  
  165. /*
  166. **    Function name : GlobalReplace
  167. **
  168. **    Description : Prepare une substitution globale.
  169. **
  170. **    Input : Le text courant.
  171. **    Ouput :
  172. */
  173. void GlobalReplace ( text )
  174.     Text *text;
  175. {
  176.     if ( SetReplaceString ( text, GLOBAL, S_KBD ) == -1 )
  177.         return;
  178.     HandleGlobal ( text );
  179. }
  180.  
  181.  
  182. /*
  183. **    Function name : HandleGlobal
  184. **
  185. **    Description : Substitution globale.
  186. **
  187. **    Input : Le text courant.
  188. **    Ouput :
  189. */
  190. static void HandleGlobal ( text )
  191.     Text *text;
  192. {
  193.     register int line, newpos, modif;
  194.     register char *start,  *end;
  195.  
  196.     line = text -> no_current_line;
  197. /*    HoleToLeft ( text -> buf ); */
  198.     start = (char *) RightBuf ( text -> buf );
  199.     end = (char *) BottomBuf ( text -> buf );
  200.  
  201.     while ( (newpos=BmSearch( start, str_old,  end - start, FORWARD )) != -1 ) {
  202.         (void) MoveHole ( text -> buf, newpos + strlen (str_old)); /* On se place a la fin du mot */
  203.         DeleteNchar ( text -> buf, strlen ( str_old) );
  204.         InsertNchar ( text -> buf, str_new, strlen ( str_new));
  205.         modif = True;
  206.         start = (char *) RightBuf ( text -> buf ); /* Position courante */
  207.     }
  208.        HoleToLeft ( text -> buf );
  209.     text -> no_current_line = 1;
  210.     GotoLineNumber ( text, line );
  211.     SetAndDisplayPage ( text );
  212.     if ( modif == True )
  213.         SetTextModif ( text );
  214. }
  215.  
  216.  
  217. /*
  218. **    Function name : QueryReplace
  219. **
  220. **    Description : Substitution sur demande.
  221. **
  222. **    Input : Le text courant.
  223. **    Ouput :
  224. */
  225. void QueryReplace ( text )
  226.     Text *text;
  227. {
  228.     register int newpos;
  229.     register char *start, *end;
  230.     register char *reply;
  231.     register int abort, modif, move;
  232.     char c = '\007'; /* ^G */
  233.  
  234.     if ( SetReplaceString ( text, QUERY, S_KBD ) == -1 ) return;
  235.  
  236.     start = (char *) RightBuf ( text -> buf ); 
  237.     end = (char *) BottomBuf ( text -> buf );
  238.     modif = abort = move = False;
  239.  
  240.     while ( (newpos=BmSearch( start, str_old,  end -start, FORWARD )) != -1 ) {
  241.         GotoPos ( text, start, newpos, FORWARD ); 
  242.         SetAndDisplayPage ( text );
  243.         TextCursorOn ( text );
  244.         (void) MoveHole ( text -> buf, strlen (str_old)); /* On se place a la fin du mot */
  245.         move = True;
  246.         reply = (char * ) GetString ( text, "Replace [y,n,q] : ", " " );
  247.  
  248.         if ( (reply == 0) || (strncmp(reply, &c, 1)) == 0 || (strncmp(reply, "q", 1) == 0 )) {
  249.             abort = True;
  250.             break;
  251.         }
  252.         if ( strncmp ( reply, "y", 1 ) == NULL ) {
  253.             DeleteNchar ( text -> buf, strlen ( str_old) );
  254.             InsertNchar ( text -> buf, str_new, strlen ( str_new));
  255.             modif = True;
  256.         }
  257.         start = (char *) RightBuf ( text -> buf ); 
  258.         end = (char *) BottomBuf ( text -> buf );
  259.     }
  260.  
  261.     if ( abort == True )
  262.         DisplayMessage ( text -> mwin, "Abort" );
  263.     else
  264.         DisplayMessage ( text -> mwin, "Done" );
  265.     
  266.     /* On revient au debut du mot */
  267. /*
  268.     if ( move == True )
  269.         (void) MoveHole ( text -> buf,  - (strlen (str_old)));
  270. */
  271.     SetAndDisplayPage ( text );
  272.     if ( modif == True )
  273.         SetTextModif ( text );
  274. }
  275.  
  276.  
  277. /*
  278. **    Function name : MenuForwardSearch
  279. **
  280. **    Description : Prepare la recherche en avant,
  281. **         ( a partir du menu ).
  282. **
  283. **    Input : Le text courant.
  284. **    Ouput :
  285. */
  286. void MenuForwardSearch ( text )
  287. Text *text;
  288. {
  289.     register char *str;
  290.  
  291.     if ( text -> visible != VisibilityUnobscured ) {
  292.         XRaiseWindow ( dpy, text -> w_parent );
  293.         return;
  294.     }
  295.         (void) ResetSearchString ();
  296.     if ( (str = (char *) SetString ( text, "Forward search : ", S_MENU )) == 0 )  {
  297.         DisplayMessage ( text -> mwin, "Abort" );
  298.         return;
  299.     }
  300.         (void) HandleForward ( str, text );
  301.     (void) ResetSearchString ();
  302. }
  303.  
  304.  
  305. /*
  306. **    Function name : MenuBackwardSearch
  307. **
  308. **    Description : Prepare la recherche en arriere,
  309. **        ( a partir du Menu ).
  310. **
  311. **    Input : Le text.
  312. **    Ouput :
  313. */
  314. void MenuBackwardSearch ( text )
  315. Text *text;
  316. {
  317.     register char *str;
  318.  
  319.     if ( text -> visible != VisibilityUnobscured ) {
  320.         XRaiseWindow ( dpy, text -> w_parent );
  321.         return;
  322.     }
  323.     (void) ResetSearchString ();
  324.     if ( (str = (char *) SetString ( text, "Backward search : ", S_MENU )) == 0 )  {
  325.         DisplayMessage ( text -> mwin, "Abort" );
  326.         return;
  327.     }
  328.     HandleBackward ( str, text );
  329.     (void) ResetSearchString ();
  330. }
  331.  
  332.  
  333. /*
  334. **    Function name : MenuQueryReplace
  335. **
  336. **    Description : Substitution a la demande,
  337. **         ( a partir du menu ).
  338. **
  339. **    Input : Le text.
  340. **    Ouput :
  341. */
  342. void MenuQueryReplace ( text )
  343. Text *text;
  344. {
  345.     if ( text -> visible != VisibilityUnobscured ) {
  346.         XRaiseWindow ( dpy, text -> w_parent );
  347.         return;
  348.     }
  349.     (void)  GetStringFromDialogBox ( text -> window,
  350.         "Warning : Please use esc q" );
  351. }
  352.  
  353.  
  354. /*
  355. **    Function name : MenuGlobalReplace
  356. **
  357. **    Description : Substitution globale,
  358. **        ( a partir du menu ).
  359. **
  360. **    Input : Le text courant.
  361. **    Ouput :
  362. */
  363. void MenuGlobalReplace ( text )
  364. Text *text;
  365. {
  366.     if ( text -> visible != VisibilityUnobscured ) {
  367.         XRaiseWindow ( dpy, text -> w_parent );
  368.         return;
  369.     }
  370.  
  371.     if ( SetReplaceString ( text, GLOBAL, S_MENU ) == -1 )
  372.         return;
  373.     HandleGlobal ( text );
  374. }
  375.  
  376.  
  377. /*
  378. **    Function name : BmSearch
  379. **
  380. **    Description : La recherche avec le fameux
  381. **        algo Boyer-Moore.
  382. **
  383. **    Input : voir plus loin.
  384. **    Ouput : La position relative du pattern recherche,
  385. **        sinon -1.
  386. */
  387. static int BmSearch ( buf, str, buf_len, dir )
  388.     register char *buf;    /* Le buffer */
  389.     register char *str;    /* La string */
  390.     register int buf_len;    /* Longueur du buffer */
  391.     register int dir;    /* Forward (1), Backward (-1)*/
  392. {
  393.     register int s_len = strlen ( str );
  394.     register int len = s_len -1;
  395.     register int i, j, k, t;
  396.     int index [128];
  397.     
  398.     for ( i = 0 ; i < 128 ; i++ )  index [i] = s_len;    
  399.  
  400.     for ( i = 0; i < s_len; i++ ) {
  401.         k = ( dir == FORWARD ) ? len - i : i;
  402.         if ( index [(int) str [k]] == s_len ) 
  403.             index [(int) str [k]] = i;
  404.     }
  405.  
  406. #ifdef DEBUG
  407.     for ( i = 0 ; i < 128 ; i++ ) 
  408.         if ( index[i] != s_len )
  409.             fprintf ( stderr, "index %c %d = %d\n", i, index [i],  (char) i);
  410. #endif DEBUG
  411.     for ( i = ( dir == FORWARD) ? len : 0, 
  412.         j = ( dir == FORWARD) ? len : 0;
  413.         (( dir == FORWARD) ? ( j>= 0) : (j <= len));
  414.         i -= ( dir == FORWARD) ? FORWARD : BACKWARD,
  415.         j -= ( dir == FORWARD) ? FORWARD : BACKWARD ) { 
  416. #ifdef DEBUG
  417.     (void) fprintf ( stderr, "i = %d, j = %d\n", i, j );
  418. #endif DEBUG
  419.         while ( buf [i] != str [j] ) {
  420.             t = index [(int) buf [i] ];
  421.             if ( dir == FORWARD ) {
  422.                 i += (( s_len - j ) > t) ? s_len - j : t;
  423.                 if ( i >= buf_len +1 ) return -1;
  424.                 j = len;
  425.             }
  426.             else {
  427. #ifdef DEBUG 
  428.     (void) fprintf ( stderr, "buf[%d] = %c str[%d] = %c t = %d\n", i, buf[i], j, str[j], t );
  429. #endif
  430. #undef DEBUG
  431.                 i -= ( j > t) ? s_len : t; 
  432.  
  433.                 if ( (buf_len +1 +i) < 0 ) return -1; 
  434.                 j = 0; 
  435.             }
  436.         }
  437.     }
  438.     return ( dir == FORWARD ) ? (i + 1) : (- ( i - s_len -1 ));
  439. }
  440.  
  441.  
  442. /*
  443. **    Function name : SetString
  444. **
  445. **    Description : Positionne le pattern a rechercher.
  446. **
  447. **    Input : Le text courant, le prompt, clavier/menu
  448. **
  449. **    Ouput : Le pattern.
  450. */
  451. static char *SetString ( text, prompt, from )
  452.     Text *text;
  453.     register char *prompt;
  454.     register int from;
  455. {
  456.     register char *str;
  457.     char c = '\007'; /* ^G */
  458.     register int len;
  459.  
  460.     if ( (str_save == 0) || (strlen (str_save)) == 0 ) {
  461.         if ( from == S_KBD )
  462.             str = (char *) GetString ( text, prompt, (char *) 0 );
  463.         else
  464.             str = ( char *) GetStringFromDialogBox ( text -> window, prompt );
  465.  
  466.         if ( str == 0 )
  467.             return 0;
  468.         if ( strncmp(str, &c, 1) == 0 ) {
  469.             abort_debug = True;
  470.             return 0;
  471.         }
  472.         if ( str_save != 0 )
  473.             (void) free ( str_save );
  474.         len = strlen (str);
  475.         str_save = (char *) malloc ( (unsigned) len + 1);
  476.         (void) strncpy ( str_save, str,  len);
  477.         *(str_save + len) = '\0';
  478.     }
  479.     return str_save;
  480. }
  481.  
  482.  
  483. /*
  484. **    Function name : SetReplaceString
  485. **
  486. **    Description : Positionne les patterns utilises
  487. **        lors des substitutions.
  488. **
  489. **    Input : Le text courant, Query/Global, menu/clavier.
  490. **    Ouput : Ok 0, sinon -1.
  491. */
  492. static int SetReplaceString ( text, type, from )
  493.     Text *text;
  494.     register int type;
  495.     register int from;
  496. {
  497.     register char *str;
  498.     char buf [64], tmp[64];
  499.     register int len;
  500.  
  501.     if ( type == GLOBAL )
  502.         (void) strcpy ( tmp, "Global replace," );
  503.     else
  504.         (void) strcpy ( tmp, "Query replace," );    
  505.     (void) ResetSearchString ();
  506.     (void) strcpy ( buf, tmp );
  507.     (void) strcat ( buf, " Old String : " );
  508.     if ( (str = (char *) SetString ( text, buf, from )) == 0 ) {
  509.         DisplayMessage ( text -> mwin, "Abort" );
  510.         return -1;
  511.     }
  512.     len = strlen (str);
  513.     if ( str_old != 0 )
  514.         (void) free ( str_old );
  515.     str_old = (char * ) malloc ( (unsigned) len + 1);
  516.     (void) strncpy ( str_old, str, len );
  517.     *(str_old + len) = '\0';
  518.  
  519.     (void) ResetSearchString ();
  520.  
  521.     buf [0] = '\0';
  522.     (void) strcpy ( buf, tmp );
  523.     (void) strcat ( buf, " New String : " );
  524.  
  525.     if ( (str = (char *) SetString ( text, buf, from )) == 0 ) {
  526.         if ( abort_debug == True ) {
  527.             DisplayMessage ( text -> mwin, "Abort" );
  528.             abort_debug = False;
  529.             return -1;
  530.         }
  531.         else {
  532.             (void) strcpy ( buf, "" );
  533.             str = buf;
  534.         }
  535.     }
  536.  
  537.     len = strlen (str);
  538.     if ( str_new != 0 )
  539.         (void) free ( str_new );
  540.     str_new = (char *) malloc ( (unsigned) len + 1 );
  541.     (void) strncpy ( str_new, str, len);
  542.     *(str_new+ len) = '\0';
  543.     (void) ResetSearchString ();
  544.     return 0;
  545. }
  546.  
  547.  
  548. /*
  549. **    Function name : GotoPos
  550. **
  551. **    Description : Va a la position relative a
  552. **        partir de la position courante.
  553. **
  554. **    Input : Le text cournant, la position de depart,
  555. **        nb octets, direction.
  556. **
  557. **    Ouput :
  558. */
  559. void GotoPos ( text, start, newpos, dir )
  560.     Text *text;
  561.     register char *start;
  562.     register int newpos;
  563.     register int dir;
  564. {
  565.     register int line;
  566.     register int x = ( dir == FORWARD ) ? newpos : -newpos;
  567.  
  568.     line = GetNewLine ( start, x );
  569.     text -> no_current_line += (dir == FORWARD ) ? line : -line;
  570.  
  571.     (void) MoveHole ( text -> buf, x );    
  572.     if ( line != 0 ) {
  573.         if ( (line > (( dir == FORWARD) ? text -> n2 : text -> n1 )))
  574.             CurrentLineToMiddle ( text );
  575.         else {
  576.             text -> n1 += (dir == FORWARD) ? line : -line;
  577.             text -> n2 -= (dir == FORWARD) ? line : -line;                
  578.             SetAndDisplayPage ( text );
  579.         }
  580.     }
  581. }
  582.  
  583.  
  584. /*
  585. **    Function name : DeleteStrings
  586. **
  587. **    Description : 
  588. **    Input : 
  589. **    Ouput :
  590. */
  591. void DeleteStrings ()
  592. {
  593.        if ( str_save != 0 )
  594.         (void) free ( str_save );
  595.        if ( str_old != 0 )   
  596.         (void) free ( str_old );
  597.           if ( str_new != 0 )
  598.         (void) free ( str_new );
  599. }
  600.  
  601.  
  602. /*
  603. **    Function name : ResetSearchString
  604. **
  605. **    Description : 
  606. **    Input : 
  607. **    Ouput :
  608. */
  609. void ResetSearchString ()
  610. {
  611.     if ( str_save != 0 )
  612.         (void) free ( str_save );
  613.     str_save = 0;
  614. }
  615.  
  616.